import type { ElTree } from "element-plus";
import type { Ref } from "vue";
import { ElMessage } from "element-plus";
import { nextTick, ref } from "vue";
import { menuApi, roleApi } from "@/api";
import { $t } from "@/plugins/i18n";
import { apiCall } from "@/utils/http/apiCall";

interface UseRoleAssignTree {
    /** 菜单树引用 */
    treeRef: Ref<InstanceType<typeof ElTree> | undefined>;
    /** 选中的节点 ID */
    checkedIds: Ref<string[]>;
    /** 菜单树加载状态 */
    treeLoading: Ref<boolean>;
    /** 菜单树数据 */
    treeData: Ref<Array<any>>;
    /** 父子关联 */
    checkStrictly: Ref<boolean>;
    /** 树展开状态 */
    isExpanded: Ref<boolean>;
    /** 按钮加载状态 */
    submitLoading: Ref<boolean>;
    /** 展开全部 */
    expandAll: () => void;
    /** 折叠全部 */
    collapseAll: () => void;
    /** 初始化数据 */
    initData: (id: string | undefined | null) => Promise<void>;
    /** 重置状态 */
    resetTree: () => void;
    /** 提交角色权限 */
    handleSubmit: (roleId: string | undefined | null, callback?: () => void) => void;
}

/** 分配菜单树 Hook */
export const useRoleAssignTree = (): UseRoleAssignTree => {
    /** 菜单树引用 */
    const treeRef = ref<InstanceType<typeof ElTree>>();
    /** 选中的节点 ID */
    const checkedIds = ref<string[]>([]);
    /** 菜单树加载状态 */
    const treeLoading = ref(false);
    /** 菜单树数据 */
    const treeData = ref<Array<any>>([]);
    /** 父子关联 */
    const checkStrictly = ref(true);
    /** 树展开状态 */
    const isExpanded = ref(true);
    /** 按钮加载状态 */
    const submitLoading = ref(false);

    /** 展开全部 */
    function expandAll(): void {
        isExpanded.value = true;
        const nodes = treeRef.value?.store.nodesMap;
        if (!nodes) return;

        Object.values(nodes).forEach((node: any) => {
            node.expanded = true;
        });
    }

    /** 折叠全部 */
    function collapseAll(): void {
        isExpanded.value = false;
        const nodes = treeRef.value?.store.nodesMap;
        if (!nodes) return;

        Object.values(nodes).forEach((node: any) => {
            node.expanded = false;
        });
    }

    /** 初始化数据 */
    async function initData(roleId: string | undefined | null): Promise<void> {
        if (!roleId) return;
        treeLoading.value = true;
        try {
            await fetchTreeData();
            await fetchRolePermissions(roleId);
            applyCheckedKeys();
        } finally {
            treeLoading.value = false;
        }
    }

    /** 获取菜单树数据 */
    async function fetchTreeData(): Promise<void> {
        await apiCall(
            () => menuApi.listMenuTree(),
            (data) => {
                treeData.value = data || [];
            },
        );
    }

    /** 获取当前角色菜单和权限 */
    async function fetchRolePermissions(roleId: string): Promise<void> {
        await apiCall(
            () => roleApi.findRolePermissions(roleId),
            (data) => {
                checkedIds.value = [...data.menuIds, ...data.permIds];
            },
        );
    }

    /** 应用选中状态 */
    function applyCheckedKeys(): void {
        nextTick(() => {
            if (!treeRef.value) return;
            treeRef.value.setCheckedKeys(checkedIds.value, true);
        });
    }

    /** 重置状态 */
    function resetTree(): void {
        checkedIds.value = [];
        treeData.value = [];
        submitLoading.value = false;
        treeLoading.value = false;
        checkStrictly.value = true;
        isExpanded.value = true;
    }

    /** 提交角色权限 */
    function handleSubmit(roleId: string | undefined | null, callback?: () => void): void {
        if (!roleId || !treeRef.value) return;

        const checkedNodes = treeRef.value.getCheckedNodes(false, true);
        const menuIds: string[] = [];
        const permIds: string[] = [];
        checkedNodes.forEach((node) => {
            if (node.meta?.menuType === "button") {
                permIds.push(String(node.id));
            } else {
                menuIds.push(String(node.id));
            }
        });

        submitLoading.value = true;

        apiCall(
            () => roleApi.updateRolePermissions({
                roleId,
                menuIds,
                permIds,
            }),
            (data, resp) => {
                ElMessage.success($t(resp.message));
                callback?.();
            },
            {
                onFinally: () => {
                    submitLoading.value = false;
                },
            },
        );
    }

    return {
        treeRef,
        checkedIds,
        treeLoading,
        treeData,
        checkStrictly,
        isExpanded,
        expandAll,
        collapseAll,
        initData,
        submitLoading,
        resetTree,
        handleSubmit,
    };
};
